/* USER CODE BEGIN Header */
/**
 ******************************************************************************
 * @file    can.c
 * @brief   This file provides code for the configuration
 *          of the CAN instances.
 ******************************************************************************
 * @attention
 *
 * Copyright (c) 2024 STMicroelectronics.
 * All rights reserved.
 *
 * This software is licensed under terms that can be found in the LICENSE file
 * in the root directory of this software component.
 * If no LICENSE file comes with this software, it is provided AS-IS.
 *
 ******************************************************************************
 */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "can.h"

/* USER CODE BEGIN 0 */
#include "lift_info.h"
/* USER CODE END 0 */

CAN_HandleTypeDef hcan;

/* CAN init function */
void MX_CAN_Init(void)
{

  /* USER CODE BEGIN CAN_Init 0 */

  /* USER CODE END CAN_Init 0 */

  /* USER CODE BEGIN CAN_Init 1 */

  /* USER CODE END CAN_Init 1 */
  hcan.Instance = CAN1;
  hcan.Init.Prescaler = 80;
  hcan.Init.Mode = CAN_MODE_NORMAL;
  hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;
  hcan.Init.TimeSeg1 = CAN_BS1_4TQ;
  hcan.Init.TimeSeg2 = CAN_BS2_4TQ;
  hcan.Init.TimeTriggeredMode = DISABLE;
  hcan.Init.AutoBusOff = DISABLE;
  hcan.Init.AutoWakeUp = DISABLE;
  hcan.Init.AutoRetransmission = ENABLE;
  hcan.Init.ReceiveFifoLocked = DISABLE;
  hcan.Init.TransmitFifoPriority = DISABLE;
  if (HAL_CAN_Init(&hcan) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN CAN_Init 2 */
    CAN_FilterTypeDef can_filter;

    can_filter.FilterActivation     = CAN_FILTER_ENABLE;
    can_filter.FilterMode           = CAN_FILTERMODE_IDMASK;
    can_filter.FilterScale          = CAN_FILTERSCALE_32BIT;
    can_filter.FilterIdHigh         = 0;
    can_filter.FilterIdLow          = 0;
    can_filter.FilterMaskIdHigh     = 0;
    can_filter.FilterMaskIdLow      = 0;
    can_filter.FilterBank           = 0;
    can_filter.FilterFIFOAssignment = CAN_FILTER_FIFO1;
    can_filter.SlaveStartFilterBank = 14;
    if (HAL_CAN_ConfigFilter(&hcan, &can_filter) != HAL_OK) {
        Error_Handler();
    }

    if (HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO1_MSG_PENDING) != HAL_OK) {
        Error_Handler();
    }

    if (HAL_CAN_Start(&hcan) != HAL_OK) {
        Error_Handler();
    }
  /* USER CODE END CAN_Init 2 */

}

void HAL_CAN_MspInit(CAN_HandleTypeDef* canHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(canHandle->Instance==CAN1)
  {
  /* USER CODE BEGIN CAN1_MspInit 0 */

  /* USER CODE END CAN1_MspInit 0 */
    /* CAN1 clock enable */
    __HAL_RCC_CAN1_CLK_ENABLE();

    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**CAN GPIO Configuration
    PA11     ------> CAN_RX
    PA12     ------> CAN_TX
    */
    GPIO_InitStruct.Pin = GPIO_PIN_11;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_12;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* CAN1 interrupt Init */
    HAL_NVIC_SetPriority(CAN1_RX1_IRQn, 1, 0);
    HAL_NVIC_EnableIRQ(CAN1_RX1_IRQn);
  /* USER CODE BEGIN CAN1_MspInit 1 */

  /* USER CODE END CAN1_MspInit 1 */
  }
}

void HAL_CAN_MspDeInit(CAN_HandleTypeDef* canHandle)
{

  if(canHandle->Instance==CAN1)
  {
  /* USER CODE BEGIN CAN1_MspDeInit 0 */

  /* USER CODE END CAN1_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_CAN1_CLK_DISABLE();

    /**CAN GPIO Configuration
    PA11     ------> CAN_RX
    PA12     ------> CAN_TX
    */
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_11|GPIO_PIN_12);

    /* CAN1 interrupt Deinit */
    HAL_NVIC_DisableIRQ(CAN1_RX1_IRQn);
  /* USER CODE BEGIN CAN1_MspDeInit 1 */

  /* USER CODE END CAN1_MspDeInit 1 */
  }
}

/* USER CODE BEGIN 1 */

#include "sh_sm.h"
#include "system_sm.h"

static void board_can_send_msg(CAN_HandleTypeDef *hcan, uint8_t *buf, uint8_t size, uint16_t cmd)
{
    CAN_TxHeaderTypeDef tx_header;
    uint32_t mail_box;

    tx_header.StdId = cmd;
    tx_header.ExtId = 0;
    tx_header.IDE   = CAN_ID_STD;
    tx_header.RTR   = CAN_RTR_DATA;
    tx_header.DLC   = size > 8 ? 8 : size;
    HAL_CAN_AddTxMessage(hcan, &tx_header, buf, &mail_box);
}

#define CANOPEN_ENCODER_ID 0x04

static void canopen_lss_config_analysis(uint8_t *data)
{
    switch (data[0]) {
    /* 节点ID配置 */
    case 0x11:
        /* 无错误 */
        if (data[1] == 0) {
//            system_sm_send_event(EVENT_CAN_SET_NODE_ID_OK);
        }
        break;

    /* 从站保存配置回复 */
    case 0x17:
        /* 无错误 */
        if (data[1] == 0) {
//            system_sm_send_event(EVENT_CAN_SAVE_CONF_OK);
        }
        break;

    default:
        break;
    }
}

#define SENSOR_NODE_ID 4

enum canopen_node_operation_state {
    CANOPEN_NODE_STATE_STOPPED = 4,
    CANOPEN_NODE_STATE_OPERATIONAL = 5,
    CANOPEN_NODE_STATE_PRE_OPERATIONAL = 127,
};

enum canopen_nmt_cmd {
    CANOPEN_NMT_CMD_START = 1,
    CANOPEN_NMT_CMD_STOP = 2,
    CANOPEN_NMT_CMD_GO_PRE_OPERATION = 128,
    CANOPEN_NMT_CMD_RESET_NODE = 129,
    CANOPEN_NMT_CMD_RESET_COMMUNICATION = 130,
};

struct can_info {
    uint16_t cob_id;
    uint8_t  slave_id;
    uint8_t  operation_state;
};

static struct can_info can_info = {0};

static void can_send_nmt_cmd(enum canopen_nmt_cmd cmd, uint8_t id)
{
    uint8_t send_buf[2] = {0};

    send_buf[0] = cmd;
    send_buf[1] = id;
    board_can_send_msg(&hcan, send_buf, 2, 0);
}

static void can_protocol_analysis(CAN_HandleTypeDef *hcan, CAN_RxHeaderTypeDef *rx_header, uint8_t *data)
{
    can_info.cob_id  = rx_header->StdId & 0x780;
    can_info.slave_id = rx_header->StdId & 0x7F;

    if (rx_header->StdId == 0x7E4) {
        canopen_lss_config_analysis(data);
    }

    switch (can_info.cob_id) {
        /* 心跳帧 */
        case 0x700:
            can_info.operation_state = data[0];
            if (can_info.operation_state != CANOPEN_NODE_STATE_OPERATIONAL) {
                can_send_nmt_cmd(CANOPEN_NMT_CMD_START, can_info.slave_id);
            }
            break;

        /* 数据帧 */
        case 0x180:
        case 0x280:
            lift_info_analysis(data);
            break;

        default:
            break;
    }
}

void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
    static uint8_t can_rec_buf[8] = {0};

    if (hcan->Instance == CAN1) {
        CAN_RxHeaderTypeDef RxHeader;
        HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO1, &RxHeader, can_rec_buf);
        can_protocol_analysis(hcan, &RxHeader, can_rec_buf);
    }
}

// /* 配置状态 */
// void sys_sm_state_canopen_config_cb(const sh_event_msg_t *e)
// {
//     switch (e->id) {
//     case EVENT_CAN_SET_NODE_ID_OK:
//         break;

//     case EVENT_CAN_SAVE_CONF_OK:
//         break;

//     default:
//         break;
//     }
// }
/* USER CODE END 1 */
